﻿using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class PoolManager : ModuleBase<PoolManager>
{
    public List<PrefabArray> prefabArrays = new List<PrefabArray>();
    public List<PrefabCache> delayCollect = new List<PrefabCache>();


    public override void Init()
    {
        Framework.Instance.AddUpdate(this);
    }

    public override void Update(float dt)
    {
        //销毁过期对象
        foreach (PrefabArray array in prefabArrays)
        {
            if (array.during > 0)
            {
                List<PrefabCache> caches = array.caches;
                for (int i = caches.Count - 1; i >= 0; i--)
                {
                    PrefabCache cache = caches[i];
                    cache.time -= dt;
                    if (cache.time <= 0)
                    {
                        caches.RemoveAt(i);
                        Object.DestroyImmediate(cache.prefab);
                    }
                }
            }
        }

        //延迟回收对象
        for (int i = delayCollect.Count - 1; i >= 0; i--)
        {
            PrefabCache cache = delayCollect[i];
            cache.time -= dt;
            if (cache.time <= 0)
            {
                delayCollect.RemoveAt(i);
                DestoryPrefab(cache.prefab);
            }
        }
    }

    public PrefabArray GetArray(string key)
    {
        PrefabArray array = null;
        foreach (PrefabArray arr in prefabArrays)
        {
            if (arr.key == key)
            {
                array = arr;
                break;
            }
        }
        return array;
    }

    public void GetPrafab(string path, string name, string ext, UnityAction<GameObject> onLoaded, float delayTime = 0)
    {
        string key = string.Format("{0}/{1}.{2}", path, name, ext);

        PrefabArray array = GetArray(key);
        GameObject prefab = null;
        if (array != null)
        {
            List<PrefabCache> caches = array.caches;
            int index = caches.Count - 1;
            if (index >= 0)
            {
                prefab = caches[index].prefab;
                prefab.SetActive(true);
                caches.RemoveAt(index);
            }
        }

        if (prefab == null)
        {
            LoadManager.Instance.LoadAsset(path, name, ext, typeof(GameObject), data =>
            {
                GameObject go = Object.Instantiate(data as GameObject);
                go.AddComponent<PrefabKey>().Key = key;
                onLoaded(go);
                AddDelayCollect(go, delayTime);
            }
            , false);
        }
        else
        {
            onLoaded(prefab);
            AddDelayCollect(prefab, delayTime);
        }
    }

    //延迟回收
    public void AddDelayCollect(GameObject go, float delay)
    {
        if (delay > 0)
            delayCollect.Add(new PrefabCache(go, delay));
    }

    public void DestoryPrefab(GameObject prefab)
    {
        PrefabKey prefabKey = prefab.GetComponent<PrefabKey>();
        if (prefabKey)
        {
            PrefabArray array = GetArray(prefabKey.Key);
            if (array == null)
            {
                array = new PrefabArray(prefabKey.Key);
                prefabArrays.Add(array);
            }
            array.AddPrefab(prefabKey.gameObject);
        }
    }
}

public class PrefabArray
{
    public string key;
    public float during;
    public List<PrefabCache> caches;

    public PrefabArray(string key, float during = 0)
    {
        this.key = key;
        this.during = during;
        caches = new List<PrefabCache>();
    }

    public void AddPrefab(GameObject go)
    {
        go.SetActive(false);
        caches.Add(new PrefabCache(go, during));
    }
}

public class PrefabCache
{
    public GameObject prefab;
    public float time;

    public PrefabCache(GameObject go, float t)
    {
        prefab = go;
        time = t;
    }
}